package org.example.aaaatest.jsonString;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.utils.IOUtils;

import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FileProcessor {

    private final ReentrantLock lock = new ReentrantLock();

    public Map<String, Object> processFile(String productId) {
        String version = getLatestVersion(productId);
        if (version == null) return Collections.emptyMap();

        int status = getDownloadStatus(productId, version);
        if (status != 1) return Collections.emptyMap();

        if (!lock.tryLock()) return Collections.emptyMap();

        try {
            Path downloadDir = Paths.get("download", productId, version);
            List<Path> files = collectFiles(downloadDir);
            if (files.isEmpty()) return Collections.emptyMap();

            Map<Path, List<Path>> groupedFiles = groupFilesByParent(files);
            processGroupedFiles(groupedFiles, productId);

            String outputDir = downloadDir.toString();
            int splitCount = executeSplitScript(productId, version, outputDir);
            updateStatus(productId, version, 13);

             Map<String, Object> map = new HashMap<>();
            map.put("files", getSplitFiles(outputDir, productId));
            map.put("count", splitCount);
            return map;
        } finally {
            lock.unlock();
        }
    }

    private List<Path> collectFiles(Path dir) {
        try (Stream<Path> stream = Files.list(dir)) {
            return stream.filter(Files::isRegularFile)
                         .sorted()
                         .collect(Collectors.toList());
        } catch (IOException e) {
            return Collections.emptyList();
        }
    }

    private Map<Path, List<Path>> groupFilesByParent(List<Path> files) {
        return files.stream().collect(
            Collectors.groupingBy(Path::getParent)
        );
    }

    private void processGroupedFiles(Map<Path, List<Path>> groups, String productId) {
        groups.forEach((parentDir, fileList) -> {
            Path mergedFile = parentDir.resolve(productId + ".tar");
            mergeFiles(fileList, mergedFile);
            unzipFile(mergedFile, parentDir);
            cleanupOriginalFiles(fileList);
        });
    }

    private void mergeFiles(List<Path> sources, Path target) {
        try (OutputStream out = Files.newOutputStream(target, StandardOpenOption.CREATE)) {
            for (Path file : sources) {
                Files.copy(file, out);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void unzipFile(Path source, Path targetDir) {
        try (TarArchiveInputStream tis = new TarArchiveInputStream(Files.newInputStream(source))) {
            TarArchiveEntry entry;
            while ((entry = tis.getNextTarEntry()) != null) {
                Path outputPath = targetDir.resolve(entry.getName());
                if (entry.isDirectory()) {
                    Files.createDirectories(outputPath);
                } else {
                    Files.createDirectories(outputPath.getParent());
                    try (OutputStream os = Files.newOutputStream(outputPath)) {
                        IOUtils.copy(tis, os);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void cleanupOriginalFiles(List<Path> files) {
        files.forEach(file -> {
            try {
                Files.deleteIfExists(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    private int executeSplitScript(String productId, String version, String outputDir) {
        String sourceFile = Paths.get(outputDir, productId + ".tar").toString();
        String prefix = Paths.get(outputDir, productId + ".tar_").toString();

        try {
            Process process = new ProcessBuilder(
                "split", "-b", "1G", sourceFile, prefix
            ).start();
            
            process.waitFor();
            return (int) Files.list(Paths.get(outputDir))
                             .filter(p -> p.getFileName().toString().startsWith(productId + ".tar_"))
                             .count();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    private List<String> getSplitFiles(String dir, String productId) {
        try (Stream<Path> stream = Files.list(Paths.get(dir))) {
            return stream.map(Path::getFileName)
                        .map(Path::toString)
                        .filter(name -> name.startsWith(productId + ".tar_"))
                        .sorted()
                        .collect(Collectors.toList());
        } catch (IOException e) {
            return Collections.emptyList();
        }
    }

    // 以下为模拟方法实现
    private String getLatestVersion(String productId) {
        // 实现数据库查询逻辑
        return "1.0";
    }

    private int getDownloadStatus(String productId, String version) {
        // 实现状态查询逻辑
        return 1;
    }

    private void updateStatus(String productId, String version, int status) {
        // 实现状态更新逻辑
    }
}